package com.gcloud.mesh.utils;

import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.StringUtils;



public class Base64Util {
	private static final String base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	private static final List<Integer> base64DecodeChars = Arrays.asList(
	        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	        -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57,
	        58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
	        9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1,
	        -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
	        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
	
	public static String encode (String str) {
		if (StringUtils.isBlank(str)) {
			return null;
		}
		
	    if(StringUtils.isNumeric(str))str=str.toString();
	    String out = "";
	    int i = 0, len = str.length(), c1, c2, c3;
	    str = utf16to8(str);
	    while (i < len ) {
	        c1 = charCodeAt(str.charAt(i)) & 0xff;
	        i++;
	        if (i == len) {
	            out += base64EncodeChars.charAt(c1 >> 2);
	            out += base64EncodeChars.charAt((c1 & 0x3) << 4);
	            out += "==";
	            break;
	        }
	        c2 = charCodeAt(str.charAt(i));
	        i++;
	        if (i == len) {
	            out += base64EncodeChars.charAt(c1 >> 2);
	            out += base64EncodeChars.charAt(((c1 & 0x3) << 4)
	                    | ((c2 & 0xF0) >> 4));
	            out += base64EncodeChars.charAt((c2 & 0xF) << 2);
	            out += "=";
	            break;
	        }
	        c3 = charCodeAt(str.charAt(i));
	        i++;
	        out += base64EncodeChars.charAt(c1 >> 2);
	        out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
	        out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
	        out += base64EncodeChars.charAt(c3 & 0x3F);
	    }
	    return out;
	}
	
	public static String decode (String str) {
		if (StringUtils.isBlank(str)) {
			return null;
		}
		
	    Integer c1, c2, c3, c4, i = 0, len = str.length();
	    String out = "";
	    while (i < len) {
	        /* c1 */
	        do {
	            c1 = base64DecodeChars.get(charCodeAt(str.charAt(i++)) & 0xff);
	        } while (i < len && c1 == -1);
	        if (c1 == -1)
	            break;
	        /* c2 */
	        do {
	            c2 = base64DecodeChars.get(charCodeAt(str.charAt(i++)) & 0xff);
	        } while (i < len && c2 == -1);
	        if (c2 == -1)
	            break;
	        out += fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
	        /* c3 */
	        do {
	            c3 = charCodeAt(str.charAt(i++)) & 0xff;
	            if (c3 == 61)
	                return out;
	            c3 = base64DecodeChars.get(c3);
	        } while (i < len && c3 == -1);
	        if (c3 == -1)
	            break;
	        out += fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
	        /* c4 */
	        do {
	            c4 = charCodeAt(str.charAt(i++)) & 0xff;
	            if (c4 == 61)
	                return out;
	            c4 = base64DecodeChars.get(c4);
	        } while (i < len && c4 == -1);
	        if (c4 == -1)
	            break;
	        out += fromCharCode(((c3 & 0x03) << 6) | c4);
	    }
	    return utf8to16(out);
	}
	
	private static String utf16to8 (String str) {
	    String out = "";
	    Integer i, c, len = str.length();
	    for (i = 0; i < len; i++) {
	        c = charCodeAt(str.charAt(i));
	        if ((c >= 0x0001) && (c <= 0x007F)) {
	            out += str.charAt(i);
	        } else if (c > 0x07FF) {
	            out += fromCharCode(0xE0 | ((c >> 12) & 0x0F));
	            out += fromCharCode(0x80 | ((c >> 6) & 0x3F));
	            out += fromCharCode(0x80 | ((c >> 0) & 0x3F));
	        } else {
	            out += fromCharCode(0xC0 | ((c >> 6) & 0x1F));
	            out += fromCharCode(0x80 | ((c >> 0) & 0x3F));
	        }
	    }
	    return out;
	}
	
	private static String utf8to16 (String str) {
	    String out = "";
	    Integer char2, char3, i = 0, len = str.length(), c;
	    while (i < len) {
	        c = charCodeAt(str.charAt(i++));
	        switch (c >> 4) {
	            case 0 :
	            case 1 :
	            case 2 :
	            case 3 :
	            case 4 :
	            case 5 :
	            case 6 :
	            case 7 :
	                // 0xxxxxxx
	                out += str.charAt(i - 1);
	                break;
	            case 12 :
	            case 13 :
	                // 110x xxxx 10xx xxxx
	                char2 = charCodeAt(str.charAt(i++));
	                out += fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
	                break;
	            case 14 :
	                // 1110 xxxx 10xx xxxx 10xx xxxx
	                char2 = charCodeAt(str.charAt(i++));
	                char3 = charCodeAt(str.charAt(i++));
	                out += fromCharCode(((c & 0x0F) << 12)
	                        | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
	                break;
	        }
	    }
	    return out;
	}
	
	private static Integer charCodeAt (char c) {
		
		return (c + 0);
	}
	
	private static char fromCharCode (int num) {

		return (char) num;
	}
	
	public static void main(String[] args) {
		System.out.println(encode("host=192.168.203.99&port=5900"));
	}
}